import { Cls } from "../util/Defined";
import { IRecyclePoolObj, RecyclePoolObj } from "../util/Pool";
import { TypeUtil } from "../util/TypeUtil";
import { ECSEntity } from "./ECSEntity";
import { ECSScene } from "./ECSScene";

/**
 * [ECS]实体组件
 */
export abstract class ECSCmp extends RecyclePoolObj {
	/** 所在场景 */
	scene: ECSScene;
	/** 组件附加的实体id */
	entityId: number;
	/** 组件附加的实体 */
	entity: ECSEntity;

	onFree(): void {
		this.onClear?.();
		this.scene = null;
		this.entity = null;
	}

	/**
	 * (虚方法)
	 * 添加到实体时触发
	 */
	onAdd?(): void;

	/**
	 * (虚方法)
	 * 实体初始化完成后触发
	 * 此时实体所有的组件已执行完onAdd
	 */
	onApply?(): void;

	/**
	 * (虚方法)
	 * 实体apply完并且跑完第一次sys的update逻辑后触发
	 */
	onStart?(): void;

	/**
	 * (虚方法)
	 * 从实体上移除时触发
	 * 当场景销毁时不会触发此函数 清理工作请放到onClear
	 */
	onRemove?(): void;

	/**
	 * (虚方法)
	 * 清理组件
	 */
	onClear?(): void;

	/**
	 * 从实体中移除自身
	 */
	removeSelf() {
		this.entity.removeCmp(TypeUtil.getCls(this));
	}

	/**
	 * 从场景中移除实体
	 */
	removeEntity() {
		this.entity.removeSelf();
	}

	// ============ 封装实体的一些方法方便调用 ============

	/** 实体在场景中的坐标 */
	get pos() {
		return this.entity.pos;
	}

	/**
	 * 是否存在对应组件
	 * @param cmpType 组件类型
	 */
	hasCmp(cmpType: Cls<ECSCmp>) {
		return this.entity.hasCmp(cmpType);
	}

	/**
	 * 获取对应组件类型的组件
	 * @param cmpType 组件类型
	 */
	getCmp<T extends ECSCmp>(cmpType: Cls<T>): T {
		return this.entity.getCmp(cmpType);
	}
}
